using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using Shuriken.Core.Store;
using Shuriken.Core.Utils;

namespace Shuriken.Core.UI.StandardUI
{
    public partial class frmMain : Form
    {
        private int m_DetailsSelectionIndex; // this is what the selection list current selection is
        private bool m_IgnoreListSelctionChanges = false; // Ignoring List Selection chages coming from the list control
        private Size m_StandardClientSize; 

        private long deactivated;

        #region UI Display Slot fields 
        private List<IUIDisplaySlot> m_DisplaySlots;
        private int m_CurrentDisplaySlot;

        private TextItemView AttributeInputPanelX;

        internal const int SUBJECTSLOT_INDEX = 0;
        internal const int ACTIONSLOT_INDEX = 1;
        internal const int ATTRIBUTESLOT_INDEX = 2;

        #endregion 

        public frmMain()
        {
            InitializeComponent();

            this.SuspendLayout();

            AttributeInputPanelX = new TextItemView();

            gradientPanel.Controls.Add(this.AttributeInputPanelX);

            //
            // AttributeInputPanelX
            // 

            AttributeInputPanelX.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
                        | System.Windows.Forms.AnchorStyles.Right)));
            AttributeInputPanelX.ControlSelected = false;
            AttributeInputPanelX.Location = new System.Drawing.Point(3, 167);
            AttributeInputPanelX.Margin = new System.Windows.Forms.Padding(0);
            AttributeInputPanelX.Name = "AttributeInputPanelX";
            AttributeInputPanelX.Size = new System.Drawing.Size(359, 80);
            AttributeInputPanelX.TabIndex = 2; 

            this.ResumeLayout(false);

            // This is the end of the code what needs to be implemented in the designer instead of here. 

            m_DisplaySlots = new List<IUIDisplaySlot>();

            SubjectItemController subjectSlot = new SubjectItemController(this, this.SubjectInputPanelX);
            ActionItemController actionSlot = new ActionItemController(this, this.ActionInputPanelX);
            AttributeItemController attributeSlot = new AttributeItemController(this, this.AttributeInputPanelX);
            
            m_DisplaySlots.Add(subjectSlot);
            m_DisplaySlots.Add(actionSlot);
            m_DisplaySlots.Add(attributeSlot);

            subjectSlot.SelectedSlot = true; 
            m_CurrentDisplaySlot = SUBJECTSLOT_INDEX;

            // Saving the original client size 
            m_StandardClientSize = this.gradientPanel.Size; 

        }

        /// <summary>
        /// Returns the action slot
        /// </summary>
        /// <remarks>
        /// Returns the subject slot, this is always the 2nd element 
        /// </remarks>
        internal ActionItemController ActionSlot
        {
            get
            {
                return (ActionItemController)m_DisplaySlots[ACTIONSLOT_INDEX]; 
            }
        }

        /// <summary>
        /// Returns the subject slot
        /// </summary>
        /// <remarks>
        /// Returns the subject slot, this is always the 1st element 
        /// </remarks>
        internal SubjectItemController SubjectSlot
        {
            get
            {
                return (SubjectItemController)m_DisplaySlots[SUBJECTSLOT_INDEX];
            }
        }

        /// <summary>
        /// Returns the attribute slot
        /// </summary>
        /// <remarks>
        /// Returns the attribute slot, this is always the 3rd element. 
        /// </remarks>
        internal AttributeItemController AttributeSlot
        {
            get
            {
                return (AttributeItemController)m_DisplaySlots[ATTRIBUTESLOT_INDEX];
            }
        }

        /// <summary>
        /// Returns true if the item list is visible 
        /// </summary>
        /// <returns></returns>
        internal bool IsItemListVisible()
        {
            return ctrlItemListX.Visible; 
        }

        internal void SelectItemOnItemList(int selIndex)
        {
            if (IsItemListVisible())
            {
                ctrlItemListX.SelectedIndex = selIndex; 
            }
        }

        /// <summary>
        /// Hides the item list. 
        /// </summary>
        internal void HideItemList()
        {
           ctrlItemListX.Visible = false; 
        }

        /// <summary>
        /// Shows the item list 
        /// </summary>
        internal void ShowItemList()
        {
            ctrlItemListX.Visible = true;            
        }


        internal void UpdateListWithItems(SortedDisplayItemList DisplayItems)
        {
            ctrlItemListX.BeginUpdate();
            ctrlItemListX.SetItems(DisplayItems);
            ctrlItemListX.EndUpdate();
        }

        private void frmMain_Deactivate(object sender, EventArgs e)
        {
            // Saving the time of deactivation
            deactivated = DateTime.Now.Ticks;

            Tracer.WriteVerbose("frmMain_Deactivate (frmMain.cs)", "UI");
            HideUI();
        }

        /// <summary>
        /// Returns the time when the form was last deactivated.
        /// </summary>
        /// <returns>last deactivation time in ticks</returns>
        internal long GetLastDeactivatedInTicks()
        {
            return deactivated; 
        }

        internal void PrepareItemList(BaseItemController baseUIDisplaySlot)
        {
            if (!IsItemListVisible())
            {
                // fill this list 
                UpdateListWithItems(baseUIDisplaySlot.DisplayItems);
                ShowItemList();
            }
            else
            {
                // sets the active control to the list if it is visible
                ctrlItemListX.ctrlItemListBox.Focus();
            }
        }

        /// <summary>
        /// Hides the UI
        /// </summary>
        internal void HideUI()
        {
            Tracer.WriteInfo("HideUI (frmMain.cs)", "UI");

            if (IsItemListVisible())
            {
                HideItemList();
            }

            Hide();
        }

        /// <summary>
        /// Shows the UI 
        /// </summary>
        /// <remarks>
        /// This is called when the UI needs to be shown to the user. 
        /// </remarks>
        internal void ShowUI()
        {
            Tracer.WriteInfo("ShowUI (frmMain.cs)", "UI");
            Show();
            Activate();
        }

        /// <summary>
        /// Callback from details list showing what is selected on the list
        /// </summary>
        /// <param name="DetailsIndex">index of the details</param>
        internal void DetailsSelectIndexChanged(int DetailsIndex)
        {
            // System.Diagnostics.Trace.WriteLine("DetailsSelectIndexChanged(" + DetailsIndex + ").");

            if (!m_IgnoreListSelctionChanges)
            {
                if (IsItemListVisible())
                {
                    m_IgnoreListSelctionChanges = true; 
                    // System.Diagnostics.Trace.WriteLine("m_DetailsSelectionIndex = " + DetailsIndex + ";");
                    m_DetailsSelectionIndex = DetailsIndex;
                    // System.Diagnostics.Trace.WriteLine("((BaseUIDisplaySlot)m_DisplaySlots[m_CurrentDisplaySlot]).SelectedItemIndex = m_DetailsSelectionIndex;");
                    ((BaseItemController)m_DisplaySlots[m_CurrentDisplaySlot]).SelectedItemIndex = m_DetailsSelectionIndex;
                    m_IgnoreListSelctionChanges = false; 
                }
            }
        }


        #region Display slots
        /// <summary>
        /// Returns the display slots of this UI
        /// </summary>
        /// <returns></returns>
        internal List<IUIDisplaySlot> GetDisplaySlots()
        {
            return m_DisplaySlots; 
        }

        internal int GetCurrentDisplaySlotIndex()
        {
            return m_CurrentDisplaySlot; 
        }

        /// <summary>
        /// Selects the next ui slot. 
        /// </summary>
        /// <remarks>
        /// Selects the next ui slot in a cyclic manner. 
        /// </remarks>
        internal void SelectNextUISlot()
        {
            // If the currently selected slot is nto the last one and it can be tabbed, then select the next
            // otherwise jump back to the first. 
            if (m_CurrentDisplaySlot < m_DisplaySlots.Count - 1 && m_DisplaySlots[m_CurrentDisplaySlot].IsTABPossible)
            {
                ActivateUISlot(m_CurrentDisplaySlot + 1);
            }
            else
            {
                ActivateUISlot(SUBJECTSLOT_INDEX);
            }
        }

        private void ExpandMainForm()
        {
            throw new Exception("The method or operation is not implemented.");
        }

        /// <summary>
        /// Activates the UI slot
        /// </summary>
        /// <param name="SlotIndex">index of the ui slot to activate</param>
        /// <remarks>Activates the UI slot. It also hides the item list</remarks>
        internal void ActivateUISlot(int SlotIndex)
        {
            System.Diagnostics.Debug.WriteLine("ActivateUISlot (frmMain.cs)", "UI");
            HideItemList();

            m_DisplaySlots[m_CurrentDisplaySlot].SelectedSlot = false;
            m_CurrentDisplaySlot = SlotIndex;
            m_DisplaySlots[m_CurrentDisplaySlot].SelectedSlot = true;
        }

        /// <summary>
        /// Expands the UI with the size specified 
        /// </summary>
        /// <param name="width">Expanding width by this much</param>
        /// <param name="height">Expanding height by this amount</param>
        internal void ExpandUIBy(int width, int height)
        {
            gradientPanel.Size = m_StandardClientSize + new Size(width, height);
        }

        /// <summary>
        /// Shrinks the UI to its original size.
        /// </summary>
        internal void ShrinkUIToOriginal()
        {
            gradientPanel.Size = m_StandardClientSize; 
        }
  
        #endregion

        /// <summary>
        /// Selects the current item 
        /// </summary>
        /// <param name="baseUIDisplaySlot">UI Slot requesting this operation</param>
        /// <returns></returns>
        internal bool SelectCurrentItemFromDetails(BaseItemController DisplaySlot)
        {
            if (DisplaySlot.DisplayItems != null)
            {
                if (DisplaySlot.DisplayItems.Count <= 0)
                {
                    return false; 
                }

                if (IsItemListVisible())
                {
                    return false;
                }

                // setting this to true so it does not going to mess up with the index. 
                m_IgnoreListSelctionChanges = true; 

                PrepareItemList(DisplaySlot);
                SelectItemOnItemList(DisplaySlot.SelectedItemIndex);

                m_IgnoreListSelctionChanges = false; 
            }
            return true; 
        }


        internal bool SelectPreviousItemFromDetails(BaseItemController DisplaySlot)
        {
            if(DisplaySlot.DisplayItems != null)
            {
                if (DisplaySlot.DisplayItems.Count <= 0)
                {
                    return false;
                }

                if (DisplaySlot.SelectedItemIndex <= 0)
                {
                    return false;
                }

                if (IsItemListVisible())
                {
                    return false; 
                }

                // setting this to true so it does not going to mess up with the index. 
                m_IgnoreListSelctionChanges = true; 

                PrepareItemList(DisplaySlot);
                DisplaySlot.SelectedItemIndex  = Math.Min(DisplaySlot.SelectedItemIndex - 1, m_DetailsSelectionIndex);
                SelectItemOnItemList(DisplaySlot.SelectedItemIndex);
                m_IgnoreListSelctionChanges = false; 
            }

            return true; 
        }

        internal bool SelectNextItemFromDetails(BaseItemController DisplaySlot)
        {

            if (DisplaySlot.DisplayItems != null)
            {
                if (DisplaySlot.DisplayItems.Count <= 0)
                {
                    return false;
                }

                if (DisplaySlot.SelectedItemIndex >= DisplaySlot.DisplayItems.Count - 1)
                {
                    return false;
                }

                if (IsItemListVisible())
                {
                    return false;
                }

                // setting this to true so it does not going to mess up with the index. 
                m_IgnoreListSelctionChanges = true;

                PrepareItemList(DisplaySlot);
                DisplaySlot.SelectedItemIndex = Math.Max(DisplaySlot.SelectedItemIndex + 1, m_DetailsSelectionIndex);
                SelectItemOnItemList(DisplaySlot.SelectedItemIndex);

                m_IgnoreListSelctionChanges = false;

            }

            return true; 
        }
    }
}